//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.oauth2.config.annotation.web.configurers;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.util.ProxyCreator;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.approval.*;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver;
import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
import org.springframework.security.oauth2.provider.endpoint.RedirectResolver;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.*;

/**
 * reuseRefreshToken = true;// 修改默认配置为false：不重复使用刷新token
 *
 * @author Mr.Lin
 * @date 2018/4/2 16:54
 */
public final class AuthorizationServerEndpointsConfigurer {
    private AuthorizationServerTokenServices tokenServices;
    private ConsumerTokenServices consumerTokenServices;
    private AuthorizationCodeServices authorizationCodeServices;
    private ResourceServerTokenServices resourceTokenServices;
    private TokenStore tokenStore;
    private TokenEnhancer tokenEnhancer;
    private AccessTokenConverter accessTokenConverter;
    private ApprovalStore approvalStore;
    private TokenGranter tokenGranter;
    private OAuth2RequestFactory requestFactory;
    private OAuth2RequestValidator requestValidator;
    private UserApprovalHandler userApprovalHandler;
    private AuthenticationManager authenticationManager;
    private ClientDetailsService clientDetailsService;
    private String prefix;
    private Map<String, String> patternMap = new HashMap();
    private Set<HttpMethod> allowedTokenEndpointRequestMethods = new HashSet();
    private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping;
    private boolean approvalStoreDisabled;
    private List<Object> interceptors = new ArrayList();
    private DefaultTokenServices defaultTokenServices;
    private UserDetailsService userDetailsService;
    private boolean tokenServicesOverride = false;
    private boolean userDetailsServiceOverride = false;
    //    private boolean reuseRefreshToken = true;
    private boolean reuseRefreshToken = false;// 修改默认配置为false：不重复使用刷新token
    private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator;
    private RedirectResolver redirectResolver;

    public AuthorizationServerEndpointsConfigurer() {
    }

    public AuthorizationServerTokenServices getTokenServices() {
        return (AuthorizationServerTokenServices) ProxyCreator.getProxy(AuthorizationServerTokenServices.class, new ObjectFactory<AuthorizationServerTokenServices>() {
            public AuthorizationServerTokenServices getObject() throws BeansException {
                return AuthorizationServerEndpointsConfigurer.this.tokenServices();
            }
        });
    }

    public TokenStore getTokenStore() {
        return this.tokenStore();
    }

    public TokenEnhancer getTokenEnhancer() {
        return this.tokenEnhancer;
    }

    public AccessTokenConverter getAccessTokenConverter() {
        return this.accessTokenConverter();
    }

    public ApprovalStore getApprovalStore() {
        return this.approvalStore;
    }

    public ClientDetailsService getClientDetailsService() {
        return (ClientDetailsService) ProxyCreator.getProxy(ClientDetailsService.class, new ObjectFactory<ClientDetailsService>() {
            public ClientDetailsService getObject() throws BeansException {
                return AuthorizationServerEndpointsConfigurer.this.clientDetailsService();
            }
        });
    }

    public void setClientDetailsService(ClientDetailsService clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    public OAuth2RequestFactory getOAuth2RequestFactory() {
        return (OAuth2RequestFactory) ProxyCreator.getProxy(OAuth2RequestFactory.class, new ObjectFactory<OAuth2RequestFactory>() {
            public OAuth2RequestFactory getObject() throws BeansException {
                return AuthorizationServerEndpointsConfigurer.this.requestFactory();
            }
        });
    }

    public OAuth2RequestValidator getOAuth2RequestValidator() {
        return this.requestValidator();
    }

    public UserApprovalHandler getUserApprovalHandler() {
        return this.userApprovalHandler();
    }

    public AuthorizationServerEndpointsConfigurer tokenStore(TokenStore tokenStore) {
        this.tokenStore = tokenStore;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenEnhancer) {
        this.tokenEnhancer = tokenEnhancer;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer reuseRefreshTokens(boolean reuseRefreshToken) {
        this.reuseRefreshToken = reuseRefreshToken;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenConverter accessTokenConverter) {
        this.accessTokenConverter = accessTokenConverter;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) {
        this.tokenServices = tokenServices;
        if (tokenServices != null) {
            this.tokenServicesOverride = true;
        }

        return this;
    }

    public AuthorizationServerEndpointsConfigurer redirectResolver(RedirectResolver redirectResolver) {
        this.redirectResolver = redirectResolver;
        return this;
    }

    public boolean isTokenServicesOverride() {
        return this.tokenServicesOverride;
    }

    public boolean isUserDetailsServiceOverride() {
        return this.userDetailsServiceOverride;
    }

    public AuthorizationServerEndpointsConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) {
        this.userApprovalHandler = approvalHandler;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer approvalStore(ApprovalStore approvalStore) {
        if (this.approvalStoreDisabled) {
            throw new IllegalStateException("ApprovalStore was disabled");
        } else {
            this.approvalStore = approvalStore;
            return this;
        }
    }

    public AuthorizationServerEndpointsConfigurer approvalStoreDisabled() {
        this.approvalStoreDisabled = true;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer prefix(String prefix) {
        this.prefix = prefix;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer pathMapping(String defaultPath, String customPath) {
        this.patternMap.put(defaultPath, customPath);
        return this;
    }

    public AuthorizationServerEndpointsConfigurer addInterceptor(HandlerInterceptor interceptor) {
        this.interceptors.add(interceptor);
        return this;
    }

    public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestInterceptor interceptor) {
        this.interceptors.add(interceptor);
        return this;
    }

    public AuthorizationServerEndpointsConfigurer exceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator) {
        this.exceptionTranslator = exceptionTranslator;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGranter) {
        this.tokenGranter = tokenGranter;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer requestFactory(OAuth2RequestFactory requestFactory) {
        this.requestFactory = requestFactory;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer requestValidator(OAuth2RequestValidator requestValidator) {
        this.requestValidator = requestValidator;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) {
        this.authorizationCodeServices = authorizationCodeServices;
        return this;
    }

    public AuthorizationServerEndpointsConfigurer allowedTokenEndpointRequestMethods(HttpMethod... requestMethods) {
        Collections.addAll(this.allowedTokenEndpointRequestMethods, requestMethods);
        return this;
    }

    public AuthorizationServerEndpointsConfigurer userDetailsService(UserDetailsService userDetailsService) {
        if (userDetailsService != null) {
            this.userDetailsService = userDetailsService;
            this.userDetailsServiceOverride = true;
        }

        return this;
    }

    public ConsumerTokenServices getConsumerTokenServices() {
        return this.consumerTokenServices();
    }

    public ResourceServerTokenServices getResourceServerTokenServices() {
        return this.resourceTokenServices();
    }

    public AuthorizationCodeServices getAuthorizationCodeServices() {
        return this.authorizationCodeServices();
    }

    public Set<HttpMethod> getAllowedTokenEndpointRequestMethods() {
        return this.allowedTokenEndpointRequestMethods();
    }

    public OAuth2RequestValidator getRequestValidator() {
        return this.requestValidator();
    }

    public TokenGranter getTokenGranter() {
        return this.tokenGranter();
    }

    public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() {
        return this.frameworkEndpointHandlerMapping();
    }

    public WebResponseExceptionTranslator<OAuth2Exception> getExceptionTranslator() {
        return this.exceptionTranslator();
    }

    public RedirectResolver getRedirectResolver() {
        return this.redirectResolver();
    }

    private ResourceServerTokenServices resourceTokenServices() {
        if (this.resourceTokenServices == null) {
            if (this.tokenServices instanceof ResourceServerTokenServices) {
                return (ResourceServerTokenServices) this.tokenServices;
            }

            this.resourceTokenServices = this.createDefaultTokenServices();
        }

        return this.resourceTokenServices;
    }

    private Set<HttpMethod> allowedTokenEndpointRequestMethods() {
        if (this.allowedTokenEndpointRequestMethods.isEmpty()) {
            this.allowedTokenEndpointRequestMethods.add(HttpMethod.POST);
        }

        return this.allowedTokenEndpointRequestMethods;
    }

    private ConsumerTokenServices consumerTokenServices() {
        if (this.consumerTokenServices == null) {
            if (this.tokenServices instanceof ConsumerTokenServices) {
                return (ConsumerTokenServices) this.tokenServices;
            }

            this.consumerTokenServices = this.createDefaultTokenServices();
        }

        return this.consumerTokenServices;
    }

    private AuthorizationServerTokenServices tokenServices() {
        if (this.tokenServices != null) {
            return this.tokenServices;
        } else {
            this.tokenServices = this.createDefaultTokenServices();
            return this.tokenServices;
        }
    }

    public AuthorizationServerTokenServices getDefaultAuthorizationServerTokenServices() {
        if (this.defaultTokenServices != null) {
            return this.defaultTokenServices;
        } else {
            this.defaultTokenServices = this.createDefaultTokenServices();
            return this.defaultTokenServices;
        }
    }

    private DefaultTokenServices createDefaultTokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(this.tokenStore());
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setReuseRefreshToken(this.reuseRefreshToken);
        tokenServices.setClientDetailsService(this.clientDetailsService());
        tokenServices.setTokenEnhancer(this.tokenEnhancer());
        this.addUserDetailsService(tokenServices, this.userDetailsService);
        return tokenServices;
    }

    private TokenEnhancer tokenEnhancer() {
        if (this.tokenEnhancer == null && this.accessTokenConverter() instanceof JwtAccessTokenConverter) {
            this.tokenEnhancer = (TokenEnhancer) this.accessTokenConverter;
        }

        return this.tokenEnhancer;
    }

    private AccessTokenConverter accessTokenConverter() {
        if (this.accessTokenConverter == null) {
            this.accessTokenConverter = new DefaultAccessTokenConverter();
        }

        return this.accessTokenConverter;
    }

    private TokenStore tokenStore() {
        if (this.tokenStore == null) {
            if (this.accessTokenConverter() instanceof JwtAccessTokenConverter) {
                this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) this.accessTokenConverter());
            } else {
                this.tokenStore = new InMemoryTokenStore();
            }
        }

        return this.tokenStore;
    }

    private ApprovalStore approvalStore() {
        if (this.approvalStore == null && this.tokenStore() != null && !this.isApprovalStoreDisabled()) {
            TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
            tokenApprovalStore.setTokenStore(this.tokenStore());
            this.approvalStore = tokenApprovalStore;
        }

        return this.approvalStore;
    }

    private boolean isApprovalStoreDisabled() {
        return this.approvalStoreDisabled || this.tokenStore() instanceof JwtTokenStore;
    }

    private ClientDetailsService clientDetailsService() {
        if (this.clientDetailsService == null) {
            this.clientDetailsService = new InMemoryClientDetailsService();
        }

        if (this.defaultTokenServices != null) {
            this.addUserDetailsService(this.defaultTokenServices, this.userDetailsService);
        }

        return this.clientDetailsService;
    }

    private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) {
        if (userDetailsService != null) {
            PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
            provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper(userDetailsService));
            tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
        }

    }

    private UserApprovalHandler userApprovalHandler() {
        if (this.userApprovalHandler == null) {
            if (this.approvalStore() != null) {
                ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler();
                handler.setApprovalStore(this.approvalStore());
                handler.setRequestFactory(this.requestFactory());
                handler.setClientDetailsService(this.clientDetailsService);
                this.userApprovalHandler = handler;
            } else {
                if (this.tokenStore() == null) {
                    throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided");
                }

                TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler();
                userApprovalHandler.setTokenStore(this.tokenStore());
                userApprovalHandler.setClientDetailsService(this.clientDetailsService());
                userApprovalHandler.setRequestFactory(this.requestFactory());
                this.userApprovalHandler = userApprovalHandler;
            }
        }

        return this.userApprovalHandler;
    }

    private AuthorizationCodeServices authorizationCodeServices() {
        if (this.authorizationCodeServices == null) {
            this.authorizationCodeServices = new InMemoryAuthorizationCodeServices();
        }

        return this.authorizationCodeServices;
    }

    private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator() {
        if (this.exceptionTranslator != null) {
            return this.exceptionTranslator;
        } else {
            this.exceptionTranslator = new DefaultWebResponseExceptionTranslator();
            return this.exceptionTranslator;
        }
    }

    private RedirectResolver redirectResolver() {
        if (this.redirectResolver != null) {
            return this.redirectResolver;
        } else {
            this.redirectResolver = new DefaultRedirectResolver();
            return this.redirectResolver;
        }
    }

    private OAuth2RequestFactory requestFactory() {
        if (this.requestFactory != null) {
            return this.requestFactory;
        } else {
            this.requestFactory = new DefaultOAuth2RequestFactory(this.clientDetailsService());
            return this.requestFactory;
        }
    }

    private OAuth2RequestValidator requestValidator() {
        if (this.requestValidator != null) {
            return this.requestValidator;
        } else {
            this.requestValidator = new DefaultOAuth2RequestValidator();
            return this.requestValidator;
        }
    }

    private List<TokenGranter> getDefaultTokenGranters() {
        ClientDetailsService clientDetails = this.clientDetailsService();
        AuthorizationServerTokenServices tokenServices = this.tokenServices();
        AuthorizationCodeServices authorizationCodeServices = this.authorizationCodeServices();
        OAuth2RequestFactory requestFactory = this.requestFactory();
        List<TokenGranter> tokenGranters = new ArrayList();
        tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails, requestFactory));
        tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
        ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
        tokenGranters.add(implicit);
        tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
        if (this.authenticationManager != null) {
            tokenGranters.add(new ResourceOwnerPasswordTokenGranter(this.authenticationManager, tokenServices, clientDetails, requestFactory));
        }

        return tokenGranters;
    }

    private TokenGranter tokenGranter() {
        if (this.tokenGranter == null) {
            this.tokenGranter = new TokenGranter() {
                private CompositeTokenGranter delegate;

                public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
                    if (this.delegate == null) {
                        this.delegate = new CompositeTokenGranter(AuthorizationServerEndpointsConfigurer.this.getDefaultTokenGranters());
                    }

                    return this.delegate.grant(grantType, tokenRequest);
                }
            };
        }

        return this.tokenGranter;
    }

    private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() {
        if (this.frameworkEndpointHandlerMapping == null) {
            this.frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping();
            this.frameworkEndpointHandlerMapping.setMappings(this.patternMap);
            this.frameworkEndpointHandlerMapping.setPrefix(this.prefix);
            this.frameworkEndpointHandlerMapping.setInterceptors(this.interceptors.toArray());
        }

        return this.frameworkEndpointHandlerMapping;
    }
}
